プログラム名：TouhouSuperExtracter

用途：東方系ゲームで使われているアーカイブファイルを展開＆一般形式へ変換



対応フォーマット：
* 東方本家
東方萃夢想(.dat)
東方緋想天(.dat)
東方地霊殿(.dat)
東方星蓮船(.dat)
東方非想天測(.dat)
東方ダブルスポイラー(.dat)
東方妖精大戦争(.dat)
東方神霊廟(.dat)
東方心綺楼(.pak)
東方輝針城(.dat)
弾幕アマノジャク(.dat)
東方深秘録コミケ体験版(.pak)
東方深秘録Web体験版(.pak)
東方深秘録(.pak)
東方紺珠伝(.dat)
東方憑依華ディスク版&Steam版(.pak)
東方天空璋(.dat)

* その他
テンドーブレード(.dat)
STEINS;GATE(.npa)
不思議の幻想郷(.bin)
不思議の幻想郷オリジン-始まりの神隠し編-(.bin)
CHAOS;HEAD(.npa)
不思議の幻想郷2 みらくるパーティー体験版(.dat)
みらくる超パーティー-早苗と天子の幻想迷宮-トライアル版(.dat)
WOLF RPG(.wolf)
不思議の幻想郷3TRIAL(.dat)
不思議の幻想郷クロニクル TRIAL.Ver(.bin)
みらくる超パーティーPLUSトライアル版(.dat)
DxLib(V4/V6)使用アプリ(.dat .dxa)
収集荷取体験版(.pak)
Steins;Gate0(.mpk)



使い方：
展開したいアーカイブ(.datファイルなど)をtouhouSE.exeにドラッグ＆ドロップで使えます。
一応コマンドライン経由でも

コマンドライン引数(分かる人向け)：
>touhouSE.exe --no-convert なんちゃら.dat
みたいに指定出来ます。
以下引数詳細。
cui
  処理終了時に入力待ちしなくなります。
no-convert
  形式変換をしなくなります(ver1.6以降で実装されたもののみ)。
paletteId
  指定したパレットIDを使用して画像化します(心綺楼/深秘録/憑依華のみ)。
  palette010.bmpを使用したい場合は
  >touhouSE.exe --paletteId 010 なんちゃら.dat
  となります。
no-recursive
  再帰的にアーカイブを展開しなくなります(ver1.6以降で実装されたもののみ)。
select
  指定されたファイル名、もしくは指定されたフルパスの物のみ展開する(ver1.6以降で実装されたもののみ)。
  形式変換前のパスを対象とする点に注意。
  例:touhouSE.exe --select palette000.bmp #{datへのパス}
select-glob
  指定されたファイル名、もしくは指定されたフルパスの物のみ展開する(ver1.6以降で実装されたもののみ)。
  形式変換前のパスを対象とする点に注意。
  *.pngといったglob記法版。
  例:touhouSE.exe --select-glob */palette*.bmp #{datへのパス}
select-regex
  指定されたファイル名、もしくは指定されたフルパスの物のみ展開する(ver1.6以降で実装されたもののみ)。
  形式変換前のパスを対象とする点に注意。
  \d*.wavといった正規表現版。
  例:touhouSE.exe --select-regex /palette\d*\.bmp #{datへのパス}
reject
  指定されたファイル名、もしくは指定されたフルパスの物を無視する(ver1.6以降で実装されたもののみ)。
  selectより優先される。
  形式変換前のパスを対象とする点に注意。
  例:touhouSE.exe --reject reimu.pat #{datへのパス}
reject-glob
  指定されたファイル名、もしくは指定されたフルパスの物を無視する(ver1.6以降で実装されたもののみ)。
  selectより優先される。
  形式変換前のパスを対象とする点に注意。
  *.pngといったglob記法版。
  例:touhouSE.exe --reject-glob *reimu* #{datへのパス}
reject-regex
  指定されたファイル名、もしくは指定されたフルパスの物を無視する(ver1.6以降で実装されたもののみ)。
  selectより優先される。
  形式変換前のパスを対象とする点に注意。
  \d*.wavといった正規表現版。
  例:touhouSE.exe --reject-regex (reimu^|yukari) #{datへのパス}
  ※^はコマンドプロンプトの都合
view-list
  展開する代わりに展開対象ファイルのフルパスを出力する(ver1.6以降で実装されたもののみ)。
  形式変換前のパスなので実際に出力されるファイル名と異なる可能性がある。
  例:touhouSE.exe --view-list --select-glob */story/* --reject-regex stage[^^/]*$ #{datへのパス}
  ※^ではなく^^なのはコマンドプロンプトの都合

ファイル解説：
touhouSE.exe    プログラム本体
cnut_converter  内部で使用している.cnutの変換に使っているソースコード
msg_converter   内部で使用している.msgの変換に使っているソースコード
touhouSE_src    ソースコード本体
touhouSE.sln    ビルド用ソリューションファイル
pal_extract.exe 緋想天用サブプログラム
anm2png.exe     地霊殿用サブプログラム
Readme.txt      今読んでいるこれ
History.txt     更新履歴

免責事項：
これに同梱されたプログラムその他が原因で発生したいかなる損害も当方は一切関知しません。
また、全てのプログラムがウイルスではないという証明も、ウイルスに感染していないという証明もありません。
自己責任でお使いください。

Q&A：
  Q：なんか一瞬だけ黒窓出て終了するんだけど
  A：ダブルクリックでは使えません、コマンドラインから使うか展開したいアーカイブをドラッグ＆ドロップしてください

  Q：不正なpalファイルですって言われるんだけど
  A：緋想天および非想天測でパレットファイルが見つからない場合に起きるエラーです。
  展開場所が一か所に揃うようにth105a.dat->th105b.dat->th105c.dat->th123a.dat->th123b.dat->th123c.datの順で
  展開していけばたいていの場合はなんとかなります。
  また、カラーパレットツールなどその他ツールの影響で発生することもあるため、どうしても起きる場合は周辺ツールを終了後に行ってください。

  Q：黒窓の表示おかしくない？
  A：パスが長すぎて1行80字を超えると酷く表示が崩れます、出力内容には影響ないので無視してください。

  Q：上に載っている以外のアーカイブは？
  A：中の人が知っているフォーマットしか展開できません、気が向いたら解析進めているかも。

  Q：PNGなのにファイルサイズでかくね？
  A：手抜きにより一部無圧縮pngになっております。

  Q：まだ一般形式にされず残ってるファイルがあるんだけど？
  A：該当する一般形式ファイルが存在しないファイルは未変換です。
  もしくは中の人の技術不足により変換できていません。

  Q：残り時間表示いい加減だね
  A：全力で手抜きです、目安以上でも以下でもありません。
  場合によってはマイナス表示になるぐらい当てになりません。
  なので、くれぐれも信用しないように。

  Q：対応フォーマット一覧に東方関係ない物が入ってるのは何故
  A：作者の趣味です。

  Q:輝針城のロゴとかぶつ切りで二つのファイルになってるんだけど
  A:実は以前の東方からそうだったのですが、気を利かせて結合していました
  大人の都合によりver1.14からバラバラに出力するようになっています。

  Q:ASSERT ERRORって表示されたんだけど、なにこれ
  A:バグです、もしくは不正なファイルです。
  その前後で表示されている内容と、どういう状況でおきたかをセットで作者に伝えると
  もしかしたら直せるかもしれません。

  Q:心綺楼でhash_#{数字やアルファベット8文字}ってフォルダがあるんだけど、元からその名前なの？
  A:いいえ、フォルダ名が不明なため暫定でそうつけています。
  心綺楼の.pakにはフォルダ名は含まれておらず、現在対応しているものは別途解析などで判明したものです。
  なのでhashなんちゃらと出ているものは作者の力不足で不明だったものだと思ってください。

  Q:深秘録でhash_#{数字やアルファベット8文字}ってファイルがあるんだけど、元からその名前なの？
  A:いいえ、深秘録はファイル名まで不明なため暫定でそうつけています。
  理由その他は心綺楼とほぼ同じで、深秘録ではファイル名まで不明なためです。

  Q：これだけはしちゃいけないって禁止事項は？
  A：処理中に対象ファイルの編集、もしくは占有。

  Q：重すぎ
  A：仕様です

  Q：ウィンドウ出ないと使いづらいんだけど
  A：GUI実装してくれる人募集中です。

  Q：dat展開も一般形式変換も既にあったような
  A：別々に使うのが面倒なので、一発で変換したかっただけです。
  個別変換はその他ツールに素晴らしいものがありますのでそちらをどうぞ

  Q：一般形式変換一個もされていない気がするんだが
  A：作者の力不足により単純にdat展開だけしか機能が乗ってない形式もあります。
  まぁそういうものだと思ってあきらめてください。

  Q：○○に対応してほしいんだけど
  A：作者のやる気次第ですが、公式の配布場所などを示してくれれば対応することもあります。
  ただし、有料作品の場合、作者が個人的に購入したものを除いて基本的に対応しません。
  ご了承ください。

  Q:その他バグをみつけた or 動作しない or 要望がある
  A:確認次第対応可能であれば対応します。
  公開しても問題が無いメールアドレスにて
  下部に記載されたアドレスまでメールをどうぞ。


メールアドレス：ｓｗｅｅｔｉｅ（あっと）ｃｌｉｃｋ３．ｏｒｇ


ライセンス：
本プログラムはlibpngを使用しています。
{{{
libpng　Copyright (C) 2004, 2006-2012 Glenn Randers-Pehrson.
}}}
本プログラムはzlibを使用しています。
{{{
zlib　Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler.
}}}

自作部分のライセンス：
・本ライセンスにおいて、全ての条項は「変更の有無を問わず、明示暗示を問わず、商業慈善を問わず、
  個人法人を問わず、保持使用を問わず、有料無料を問わず、全体一部を問わず、コピー派生を問わず
  実行ファイルソースファイルを問わず、故意錯誤を問わず」と装飾されている物として扱う。
・著作権者は本ソフトウェアに関する一切の保障義務をもたない。
・上記条項唯一の例外として、本ライセンスに違反した場合を除いて著作権者から
  本ソフトウェアに関する一切の法的措置を受ける事が無い事のみ保証される。
・著作権者やその他保持者がこのライセンスの範囲で行う活動に支障が無い範囲であれば何を行っても構わない。
・上記条項の”何を行っても構わない”には本ソフトウェアの製作者を偽っての再配布も含まれる。
・全ての権利の行使において、著作権者への連絡、著作権者やライセンス条項の記載、
  適用ライセンスなどの制限は一切存在しない。
著作権者名：sweetie


面倒な人向けライセンス解説：
libpngとzlibのライセンスをどこかに書いておけば自由に改造や再配布出来ます。
自作部分については作者やライセンスの記載義務すらありません。
再配布や改造など申告なし記述なしで好きにできます。


技術情とどうでもいい話(下に行くほど新しい)：
th105_SEを元に2形式追加したもの、新形式入れるたびに他のもので無理が出てくるというジリ貧仕様。
残り時間更新がファイル展開ごとなので、萃のような1ファイルがでかいdatだと更新がとろいし全くあてにならない。
略称をSuperEXとtouhouSEのどちらにするか悩んだ時間＞th105_SEとth075_SEの合体に掛かった時間。
なぜか途中までC言語縛りという苦行を行っていたが、結局あきらめてC++になった。　ついでにboostも導入した。
tgaのフォーマットが場所によってまるで違うことを書いていて非常に苦労した。
  最終的には一番正しそうだったGIMPさんの挙動をみて実装、なんだこれ。
  関係ないけど、手元のGIMPさんに横幅偶数ピクセルの画像を左右反転させると中央2ピクセルが反転されないバグがあった。
  でも、最新版でのチェックとか、厳密な意味での仕様ではどうなっているのか調べるのが面倒なのでバグ報告はせずに放置。
  関数版とクラス版で二重に実装されているので、いつか統一したい。
patファイルのデコーダーは手元にあるが、なぜか組み込まれていない、理由は自分でもよくわからない。
試験導入してみたASSERTマクロは意外と便利、きちんとしたものを使わなくても意外と何とかなるようだ。
BOOSTを中途半端に導入したせいでアサートが自作とboostので混在しててキモいのでいつか直す。
1から書き直している版があったのだが、新作出ちゃったしやっぱりこれのままで行くことにする。
  =>といいつつ、関数ベースがあまりにも苦痛なので、既存のはそのままにクラスでも追加できるようにした。
妖精大戦争とダブルスポイラーはなんか動いてるっぽいので対応したことにする。(DSのmsgファイルが展開できてないが気にしない)
地味に自動識別機能がついているので、地霊殿以降の物もすべて一発展開いけます。　anmとか中身まで触ってたかいがあったというものだ。
といいつつ妖精大戦争と星蓮船の区別ついてないんですけどね(つける必要性がないともいう)
VS2010にしたり、最適化スイッチ入れまくったりしたおかげで多少早くなった気がするけど気のせいかもしれない。
気付いたら東方幻想麻雀の形式が変わってて最新版じゃ動かなくなっていたが、別に対応させる必要ないかなと放置している。
npaは実はSTEINS;GATE以外でも動くんじゃないかと思っているが、試していない。
ddsの大部分は未実装、単純に画像としてではなく3D的な情報が絡むと面倒臭いため。
ddsはMSの仕様で必須と言われている条件を満たしていないファイルが多すぎたので、修正して読み込むコードが入っている。
CHAOS;HEADとSTEINS;GATEで拡張子同じなのにフォーマットが全く違う、せめて識別子ぐらいは残すべきだと思う。
みらくるパーティーは入れ子構造、ファイル名があったりなかったり、グループ単位圧縮と、厄介な処理がいっぱい。
連番で処理する都合上ダミーファイル入れるぐらいなら、全部ファイル名持たせとけばいいのにと思わないでもない。
東方のmsgファイルの仕様は地霊殿で大体基礎が固まったらしく
風神録と地霊殿にはmsgファイル互換性がなかった、ので解析しなおさないといけないんだけどやってない。
みらくる超パーティーは不思議の幻想郷シリーズなのかそうでないのか……
みら超はみらぱとほぼ同じで、暗号化が単純なxorからxor+ビットローリングになっただけ。
C言語はなんでネイティブでビットローリング指定する演算子ないの？　インラインアセンブラ書けということなのだろうか。
みら超フォーマットに変更入れたんだからファイル中のバージョン番号あげればいいのにと思わないでもない。
ふし幻からみらぱではきちんと上がってたのになぁ。
片道勇者にはまった関係でWOLF RPGに対応。
offsetが可変長のLZSSは意外と初めて見たかもしれない。
ちょっと前からアーカイブ展開とファイル形式変換を分離して
アーカイブから展開したら知ってる範囲の全形式に変換をチャレンジして～
という処理にしていたのだが、WOLF RPGのバイナリファイルがよく誤爆して別の形式に。
多少おかしなファイルでも変換できるようにしておくのは良くないですね。
>>0x10を>>10と誤字って一部ファイルだけ壊れる謎バグに悩まされたのは秘密。
WOLF RPGはfooterのバーゲンセールと化してて何ともかんとも。
ふつう一個目以外はfooterとはつけないよなぁと思いつつも、なんとなくそのまんまに。
身代わり少女をやった関係でフォルダを含む.wolfファイルが開けないことに気づく。
今までsignatureだと思っていたものが実はflagだったりなんだりで対応は結構大変でした。
フォルダ情報なんて持たせず、ファイル名が直にフォルダ名も含むようにすればいいと思うんだけどなぁ。
なんでファイルの作成日時とかまで保持しているのかは結構謎である。
輝針城体験版は試験的に新しい方の仕組みで実装してみた。
結果コード量は減ったし汎用性も上がったが、画像ファイルの結合など一部機能を削る羽目に。
風神録展開コードに試験展開の処理がなかったため、輝針城を風神録と誤解して動くバグがあった。
他の東方シリーズと合わせてanmの試験展開までやるべきなんだが
とりあえずverファイルだけで誤認はなくなったので、しばらくはこのままに。
msgは以前と変わらず。
anmは新しい方の仕組みように書き直した、風神録用anmとかぶる部分が多いので
気が向いたら抽象化したりいろいろする予定。
輝針城対応版はVS2012で作った、が、win8.1 preview上に環境を作ってしまったので
次回しれっとVS2010に戻るかもしれない。
コンパイル環境いちいち書くの面倒になったので今回から書くのやめました。
ここの行数がいい加減やばい、削除したい気もするんだけど、意外と思い出す時に便利なので悩む。
デンシャ(フリーゲーム)の展開ができなかったので修正
フォルダ名がないわ、フォルダ数かと思っていた数値は違うわで、あっている自信はない。
弾幕アマノジャクは輝針城フォーマットで変化なし
なのでフォーマット欄に弾幕アマノジャクと表示されることはない。
msgだけ命令が一個増えていたので足してある。
anmの展開に失敗していたが、単純に神霊廟フォーマットと誤認されて展開失敗していただけ。
試しにいくつかのファイル展開させて失敗したらそのフォーマットではないと分岐するのだが
弾幕アマノジャクでは運悪く神霊廟で全部成功してしまい誤認されていた。
不思議の幻想郷3の解析は難しいとの前評判があったのだがTRIALに関してはすごく簡単だった。
単純に暗号化の式がちょっと変更になっただけである。
この感じだとみらくる超パーティーから3までの製品も似たり寄ったりだと推測される。
だが、自分がプレイしていないので触らない予定、そもそもどれが未対応なのかすら把握していないし……
ところでふし幻系暗号化で使われているROR命令ってどうやって機械語吐いているのだろうか？
機械語の並びを見るにC++で開発されているように見えるが、C++でRORに相当する式は確か存在していない。
インラインアセンブラなのかな？　ちなみに本アプリでは普通にC++で書いているので遅い。
ムラサキの展開コード書いてたらそれは実はDxLib標準のアーカイブだったというオチで実装されたDxLibV4。
せっかくなのでパスワードの逆算コードを入れて、大体のDxLib使用アーカイブなら展開できるようにした。
その仕組みは、鍵長12byteの単純なxor暗号なので、ヘッダなど固定値が入る場所から逆算しているだけ。
こういうのを考えると、やはり暗号関係を自作するのは下策なのだろう、一つの想定漏れで全部無駄になるのだから。
DxLib対応コードでVC++のバグを踏み抜きバグ報告までした、詳細は http://resemblances.click3.org/?p=1734 参照。
心綺楼対応は一度諦めたが、英語化パッチの報を聞き、そちらさまのソースを参考にして実装した。
心綺楼はRSA暗号を逆に使っており、秘密鍵を知っている人のみ暗号化できるようにしている。
が、鍵長が512bitなため海外ではすでに解読済みで、英語化パッチはそのおかげで実現したようだ。
Q&Aにもあるが心綺楼はフォルダ名情報を保持していない。
ではどうなっているかというと、フォルダ名をFNV1という一方向hashに食わせたものを保持している。
とはいえ、実行時には当然相対なり絶対なりのパスで参照しているので、実際に使われている物は解読済み。
だが、使われていないファイルも相当あり、それらは総当たりなどで解析したのだが、残念がらすべては判明しなかった。
ちなみに、解析前の不明フォルダが257個あり、総当たり辞書攻撃その他で209個判明して、残り不明48個。
ファイル名はソートして格納されていたため、不明なフォルダ名に関しても前後からわかる範囲で近いフォルダに出力している。
心綺楼の専用フォーマットのうち.csv/画像/パレット/.wav/.actの五種類は変換実装済み。
心綺楼で必要だったのでsquirrelのコンパイル済みスクリプト形式である.cnutの逆コンパイルも実装済み。
とはいうものの、ちゃんとした逆コンパイルできる技術力はないので、逆アセンブル的にオレオレ中間言語に翻訳しただけ。
まぁそれでも人が読める形にはなったので、そこから人の手でちゃんとしたスクリプトに翻訳し直し、
さらに手を加えたうえで心綺楼に突っ込んで動作を改変する、というのも不可能ではないはず。
心綺楼の.actというのは、連想配列的なものと.cnutを複数含むアーカイブ。
何のために使うファイルなのかはよくわからなかったが、中の.cnutを変換したかったので展開に対応した。
個人的感想だが.actのフォーマットはミスを誘発しやすく合理性も薄い構造にみえる、設計者はもうちょっと頑張ってほしい。
.actの変換先はjsonのような何か、.cnutを含んでいてそこだけjsonではない、他は一応jsonとしてパース出来るはず。
テキストの中でファイル名が出てくるのに該当ファイルが無いのは、squirrel逆コンパイルで.nutに変換されているせい。
パレットデータの読み込み、th135b.pak展開時はどうしよう？という緋想天と同じ問題に遭遇し、
緋想天と同じく、出力済みのパレットファイルを読み込んで対応する形で実装してある。
出力済みファイルになかった場合はその旨を一度だけ表示して、無変換で出力。
一応同じ.pak内にそれっぽいファイル名があったらそれをパレットとして使う、この点は緋想天からの進歩だ。
パレットは独自形式ファイルなのだが拡張子は.bmpなので、ちょっと気を利かせて.png画像に変換して出力している。
パレット画像の形式を16*16にしたのは偶然だが、出力されたパレット画像を見るに、編集時も16*16でいじっているようだ。
パレットには32bitカラーと16bitカラーの二種類が入っており、どちらを読んでもいいようになっていた。
おそらく軽量モードだと16bitカラーで動作するようになるのだと思われる。
今回の出力では別に16bitカラーを使う理由はないので全部32bitカラーで出力している、当然パレット本体も。
.plという会話スクリプトがあるのだが、これが平文なのは変換したからではなく元から。
コンパイラを実装する暇がなかったのだろうか？
収集荷取体験版も心綺楼とほぼ同じだったのでついでに対応した。
心綺楼との差分はフォルダ名の辞書と.actのいくつか新形式。
.pakのフォーマット自体は心綺楼と同じなので展開時のフォーマット認識は心綺楼のまま。
たぶん製品版もいけるとは思うが、自分が持っていないので不明。
もし展開できてもフォルダ名が未知なものが多くてhash_ほにゃららなフォルダであふれる可能性がある。
東方深秘録体験版は展開に使う鍵が心綺楼と一緒という手抜き具合。
一応ファイル名からhashを計算するのに使われているアルゴリズムが変更になっているが、
それもFNV1からFNV1aへの更新と、FNV1の実装ミス修正、という些細なものでしかない。
フォルダ名は心綺楼と同じように調査した、総数346、判明344、不明2が最終状態。
調査していてわかったが、心綺楼と完全に同じファイルが結構な量入っていたので、
深秘録は最初心綺楼ベースで始まり、そのまま未使用なのに入りっぱなしなファイルが相当数ある様子。
心綺楼のフォルダ名hashの辞書探索ツールにバグがあることが判明し、修正したら新たに34個判明した。
深秘録は体験版二種と製品版で合計3フォーマット存在する。
コミケ体験版は上の方で説明済みなのではぶくとして
Web体験版はコミケ体験版のをベースにRSAの鍵を変更、フォルダ名情報なども色々撤去され
ついでに解析対策だろうxor処理がちょこちょこ増えた版。
製品版はさらにRSA鍵が変更になっただけでWeb体験版とほぼ同じフォーマットだが
含むファイルの都合から使われていなかった機能などがあり、それ用に追加実装が必要だった。
ファイル名もフォルダ名も含んでいないならどうやって出力してるのかと言えば、心綺楼と同じくhashを逆算した。
ちなみに、深秘録製品版には14,064個のファイルがあり、不明は170個なので98%ぐらいは逆算に成功した計算。
例大祭前日の時点でWeb体験版の展開自体は成功していた。
製品版は例大祭に行かなかったため通販で5/17午後に届き5/18には展開に成功
その後は約三週間hashの逆算に挑戦し続けていた模様。
関係ないアプリを調査していたらDxArchiveの新形式だったことが判明したので対応した。
32bitだったデータが色々64bitになっているのと、復号化に使う鍵の扱いが微妙に違う。
鍵が簡単に導出できるのは同じ、なので相変わらず鍵付きだろうと展開できる。
憑依華はRSAの鍵が違う以外は深秘録と一緒。
hashの逆算は一週間かけた、不明は474/17,507の2.7%。
深秘録よりだいぶ不明が多いがtestデータなど導出不能なファイルが多くこれが限界だった。

